bitkeeper revision 1.1159.258.166 (42a9bca7SPmMRozAfET0WOMKS0VQZA)
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Fri, 10 Jun 2005 16:15:35 +0000 (16:15 +0000)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Fri, 10 Jun 2005 16:15:35 +0000 (16:15 +0000)
Fix and simplify the seg_fixup code. It only needs to handle
instructions with GS override.
Signed-off-by: Keir Fraser <keir@xensource.com>
xen/arch/x86/x86_32/seg_fixup.c

index cc4a97c1954b934373c528998021962f2b6c4922..8a04f507d53a6063fa643d01a895f2165b9ab766 100644 (file)
@@ -292,7 +292,7 @@ int gpf_emulate_4gb(struct xen_regs *regs)
     u32           disp32 = 0;
     u8            *eip;         /* ptr to instruction start */
     u8            *pb, b;       /* ptr into instr. / current instr. byte */
-    unsigned int  *pseg = NULL; /* segment for memory operand (NULL=default) */
+    int            gs_override = 0;
 
     /* WARNING: We only work for ring-3 segments. */
     if ( unlikely(VM86_MODE(regs)) || unlikely(!RING_3(regs)) )
@@ -325,30 +325,20 @@ int gpf_emulate_4gb(struct xen_regs *regs)
         switch ( b )
         {
         case 0x67: /* Address-size override */
-            DPRINTK("Unhandleable prefix byte %02x\n", b);
-            goto fixme;
-        case 0x66: /* Operand-size override */
-        case 0xf0: /* LOCK */
-        case 0xf2: /* REPNE/REPNZ */
-        case 0xf3: /* REP/REPE/REPZ */
-            break;
         case 0x2e: /* CS override */
-            pseg = &regs->cs;
-            break;
         case 0x3e: /* DS override */
-            pseg = &regs->ds;
-            break;
         case 0x26: /* ES override */
-            pseg = &regs->es;
-            break;
         case 0x64: /* FS override */
-            pseg = &regs->fs;
+        case 0x36: /* SS override */
+            DPRINTK("Unhandled prefix %02x\n", b);
+            goto fail;
+        case 0x66: /* Operand-size override */
+        case 0xf0: /* LOCK */
+        case 0xf2: /* REPNE/REPNZ */
+        case 0xf3: /* REP/REPE/REPZ */
             break;
         case 0x65: /* GS override */
-            pseg = &regs->gs;
-            break;
-        case 0x36: /* SS override */
-            pseg = &regs->ss;
+            gs_override = 1;
             break;
         default: /* Not a prefix byte */
             goto done_prefix;
@@ -356,6 +346,12 @@ int gpf_emulate_4gb(struct xen_regs *regs)
     }
  done_prefix:
 
+    if ( !gs_override )
+    {
+        DPRINTK("Only instructions with GS override\n");
+        goto fail;
+    }
+
     decode = insn_decode[b]; /* opcode byte */
     pb++;
     if ( decode == 0 )
@@ -366,12 +362,13 @@ int gpf_emulate_4gb(struct xen_regs *regs)
     
     if ( !(decode & HAS_MODRM) )
     {
+        /* Must be a <disp32>, or bail. */
         if ( (decode & 7) != 4 )
             goto fail;
 
         if ( get_user(offset, (u32 *)pb) )
         {
-            DPRINTK("Fault while extracting <disp8>.\n");
+            DPRINTK("Fault while extracting <disp32>.\n");
             goto page_fault;
         }
         pb += 4;
@@ -409,8 +406,6 @@ int gpf_emulate_4gb(struct xen_regs *regs)
     switch ( modrm >> 6 )
     {
     case 0:
-        if ( pseg == NULL )
-            pseg = &regs->ds;
         disp32 = 0;
         if ( rm == 5 ) /* disp32 rather than (EBP) */
         {
@@ -425,8 +420,6 @@ int gpf_emulate_4gb(struct xen_regs *regs)
         break;
 
     case 1:
-        if ( pseg == NULL ) /* NB. EBP defaults to SS */
-            pseg = (rm == 5) ? &regs->ss : &regs->ds;
         if ( get_user(disp8, pb) )
         {
             DPRINTK("Fault while extracting <disp8>.\n");
@@ -437,8 +430,6 @@ int gpf_emulate_4gb(struct xen_regs *regs)
         break;
 
     case 2:
-        if ( pseg == NULL ) /* NB. EBP defaults to SS */
-            pseg = (rm == 5) ? &regs->ss : &regs->ds;
         if ( get_user(disp32, (u32 *)pb) )
         {
             DPRINTK("Fault while extracting <disp8>.\n");
@@ -457,7 +448,7 @@ int gpf_emulate_4gb(struct xen_regs *regs)
         offset += *(u32 *)memreg;
 
  skip_modrm:
-    if ( !fixup_seg((u16)(*pseg), offset) )
+    if ( !fixup_seg((u16)regs->gs, offset) )
         goto fail;
 
     /* Success! */